/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package IFSv2.Util;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Joel
 */
public class utilField {
    
    private String configFileName;
    private Map<String, String[]> fieldMap = new HashMap();;
    private javax.swing.JPanel editingPanel;
    
    private List componentList;
    ComponentMover cMover;
    final int PAD = 10;
        
    public utilField(String configFileName, javax.swing.JPanel editingPanel, Boolean editing){
    
        this.editingPanel = editingPanel;
        this.configFileName = configFileName;
        
        if(editing){
            componentList = new ArrayList();
            cMover = new ComponentMover();
            editingPanel.setLayout(null);
            captureComponents();
            init();
            //loadComponents();
            //loadConfig();
            //rebuildComponents();
            reloadComponents();
            addLabel();
        }else{
            loadConfig();
        }
        
    }
    
    public final void init(){
        loadComponents();
        loadConfig();
        reloadComponents();
    }
    
    private void addLabel(){
    
        javax.swing.JLabel lblInitialization = new javax.swing.JLabel("Initialization Mode");
        lblInitialization.setBounds((editingPanel.getWidth()/2) - 225, (editingPanel.getHeight()/2)-25, 450, 50);
        lblInitialization.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 50));
        lblInitialization.setForeground(Color.GRAY);
        editingPanel.add(lblInitialization);
    
    }
    private void loadComponents(){
        int i=0;
        for(Component component: editingPanel.getComponents()){
            System.out.print(String.valueOf(i++) +"\n");
            String[] data= new String[6];
            /*
             * Save the label(for JLabel)
             */
            if(component instanceof javax.swing.JLabel){
                data[0] = ((javax.swing.JLabel)component).getText();
            }else{
                data[0] = "";
            }
            /*
             * Save the accessibility
             */
            if(component.isVisible()){
                data[1] = "1";
            }else{
                data[1] = "0";
            }
            if(!component.isEnabled()){
                data[1] = "-1";
            }
            /*
             * Save the coordinates
             */
            data[2] = String.valueOf(component.getX());
            data[3] = String.valueOf(component.getY());
            data[4] = String.valueOf(component.getWidth());
            data[5] = String.valueOf(component.getHeight());
            
            fieldMap.put(component.getName(),data);
        }
    }
    
    
    private void reloadComponents(){
    
        int size = editingPanel.getComponentCount();
        for(int i=0; i< size; i++){
            
            String[] fieldDef = fieldMap.get(editingPanel.getComponent(i).getName());
            if(fieldDef != null){
                if(editingPanel.getComponent(i) instanceof javax.swing.JLabel){
                    javax.swing.JLabel label = (javax.swing.JLabel) editingPanel.getComponent(i);
                    label.setText(fieldDef[0]);
                }
                switch(fieldDef[1]){
                    case "1":
                        editingPanel.getComponent(i).setVisible(true);
                        editingPanel.getComponent(i).setEnabled(true);
                        break;
                    case "0":
                        editingPanel.getComponent(i).setVisible(false);
                        editingPanel.getComponent(i).setEnabled(true);
                        break;
                    case "-1":
                        editingPanel.getComponent(i).setVisible(true);
                        editingPanel.getComponent(i).setEnabled(false);
                        break;
                    default:
                        break;
                }

                editingPanel.getComponent(i).setBounds(Integer.parseInt(fieldDef[2]), Integer.parseInt(fieldDef[3]), Integer.parseInt(fieldDef[4]),Integer.parseInt(fieldDef[5]));
            }
        } 
    }
    
    private void captureComponents(){
    
        for(Component component : editingPanel.getComponents()){
            addNext(component);
        }   
    }
    
    private void rebuildComponents(){
    
        for(int i=0; i<editingPanel.getComponentCount(); i++){
            if(editingPanel.getComponent(i) instanceof javax.swing.JComboBox){
                ((javax.swing.JComboBox) editingPanel.getComponent(i)).setEditable(false);
            }
//            String[] fieldInfo =  fieldMap.get(editingPanel.getComponent(i).getName());
//            if(fieldInfo != null)
//                editingPanel.getComponent(i).setBounds(Integer.parseInt(fieldInfo[2]), Integer.parseInt(fieldInfo[3]), Integer.parseInt(fieldInfo[4]),Integer.parseInt(fieldInfo[5]));
        }
    }
    
    public void addNext(Component c)
    {
        componentList.add(c);
        c.addMouseListener(cMover);
        c.addMouseMotionListener(cMover);
        editingPanel.add(c);
        Dimension d = c.getPreferredSize();
        Point p = getNextLocation(d);
        c.setBounds(p.x, p.y, d.width, d.height);
        editingPanel.repaint();
    }
    
    private Point getNextLocation(Dimension d)
    {
        int maxX = 0, maxY = 0;
        Component c, last = null;
        Rectangle r;
        for(int j = 0; j < componentList.size(); j++)
        {
            c = (Component)componentList.get(j);
            r = c.getBounds();
            if(r.y + r.height > maxY)
            {
                maxY = r.y + r.height;
                last = c;
            }
        }
        for(int j = 0; j < componentList.size(); j++)
        {
            c = (Component)componentList.get(j);
            r = c.getBounds();
            if(r.y + r.height == maxY && r.x + r.width > maxX)
            {
                maxX = r.x + r.width;
                last = c;
            }
        }
        Point p = new Point();
        if(last == null)                                // first component
        {
            p.x = PAD;
            p.y = PAD;
            return p;
        }
        r = last.getBounds();
        int x, y;
        if(r.x + r.width + PAD + d.width < editingPanel.getWidth())  // next in row
        {
            p.x = r.x + r.width + PAD;
            p.y = r.y;
        }
        else                                            // skip to new row
        {
            p.x = PAD;
            p.y = r.y + r.height + PAD;
        }
        return p;
    }
        
    /*
     * Load the config file
     */
    private void loadConfig(){
        try {
            DataInputStream dataStream;
            BufferedReader bufferedReader;
            try (FileInputStream fileStream = new FileInputStream(configFileName)) {
                dataStream = new DataInputStream(fileStream);
                bufferedReader = new BufferedReader(new InputStreamReader(dataStream));
                String str;
                /*
                 * read the config file
                 */
                while((str = bufferedReader.readLine()) != null){
                    String [] values = str.split(":");
                    String description = values[1].substring(values[1].indexOf('(')+1, values[1].indexOf(')'));
                    String [] definition = description.split(",");
                    /*
                     * replace the default keys that were assigned by the 
                     * loadComponents function
                     */
                    if(fieldMap.containsKey(values[0])){
                        fieldMap.remove(values[0]);
                    }
                    fieldMap.put(values[0], definition);        
                }
            }
                dataStream.close();
                bufferedReader.close();
        } catch (IOException ex) {
            utilErrorHandler.printError(ex.toString(), "clsField", "loadConfig");
            /*
             * will create a function that will create a cfg file here
             */
        } 
    }
        
    /*
     * Popup menu that will display the editing options for the user
     */
    private void openPopup(final Component selectedComponent){
            /*
             * Accessibility
             */
            javax.swing.JPopupMenu menu;
            javax.swing.JMenu accessMenu;
            javax.swing.JMenuItem [] item = new javax.swing.JMenuItem[3];
            
            menu = new javax.swing.JPopupMenu();
            accessMenu = new javax.swing.JMenu("Accessibility"); 
            item[0] = new javax.swing.JMenuItem("Visible");
            item[1] = new javax.swing.JMenuItem("Hidden");
            item[2] = new javax.swing.JMenuItem("Locked");
                        
            for(int i=0; i<3; i++){
                
                accessMenu.add(item[i]);
                
                item[i].addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        openAcccessibilitySettings(((javax.swing.JMenuItem)e.getSource()).getText(), selectedComponent);
                        updateComponent(selectedComponent);
                    }

                });
            }
            menu.add(accessMenu);
            /*
             * Width settings for JTextField and JComboBox,
             * Label settings for JLabel
             */
            if(selectedComponent instanceof javax.swing.JTextField || selectedComponent instanceof javax.swing.JComboBox){
                javax.swing.JMenuItem itmLength = new javax.swing.JMenuItem("Set Length");
            
                itmLength.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        String input = javax.swing.JOptionPane.showInputDialog("Input text length:");
                        int numInput = 0;
                        try{
                            numInput = Integer.parseInt(input);
                        }catch(Exception ex){
                            javax.swing.JOptionPane.showMessageDialog(editingPanel, "Invalid input!");
                        }
                        
                        if(selectedComponent instanceof javax.swing.JTextField){
                            javax.swing.JTextField txtField = (javax.swing.JTextField) selectedComponent;
                            selectedComponent.setBounds(txtField.getX(), txtField.getY(), numInput, txtField.getHeight());
                            selectedComponent.revalidate();
                            updateComponent(selectedComponent);

                        }
                        
                    }
                });
            menu.add(itmLength);
            }
            else if(selectedComponent instanceof javax.swing.JLabel){
                javax.swing.JMenuItem itmLength = new javax.swing.JMenuItem("Set Label");
                itmLength.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        String compLabel = javax.swing.JOptionPane.showInputDialog("Input new label: ");
                        if(!compLabel.isEmpty()){
                            ((javax.swing.JLabel)selectedComponent).setText(compLabel);
                            selectedComponent.revalidate();
                            updateComponent(selectedComponent);
                        }
                    }
                });
                
                menu.add(itmLength);
            }
            
            menu.addSeparator();
            /*
             * Informations about the current status of the component
             */
            javax.swing.JMenuItem itmDetail = new javax.swing.JMenuItem("Component Detail");
            itmDetail.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    javax.swing.JOptionPane.showMessageDialog(editingPanel, "Component: "+selectedComponent.getName(),"",javax.swing.JOptionPane.INFORMATION_MESSAGE);
                }
                
            });

            menu.add(itmDetail);
            /*
             * Display the menu option
             */
            menu.show(editingPanel, selectedComponent.getX(), (selectedComponent.getY() + selectedComponent.getHeight()));    
	}
    
    private void openAcccessibilitySettings(String accessText, Component selectedComponent){
    
        switch(accessText){
        
            case "Visible":
                selectedComponent.setVisible(true);
                selectedComponent.setEnabled(true);
                break;
            case "Hidden":
                selectedComponent.setVisible(false);
                selectedComponent.setEnabled(true);
                break;
            case "Locked":
                selectedComponent.setVisible(true);
                selectedComponent.setEnabled(false);
                break;
        }
    
    
    }
    
    private void writeConfig(Component thisComponent){
            
        File file = new File(configFileName);
        
        if(file.exists()){
        
            FileOutputStream fos;
            
            if(fieldMap.containsKey(thisComponent.getName())){
                String data = thisComponent.getName() + ":(";
                String[] arrData = fieldMap.get(thisComponent.getName());
                    for( int i=0; i<arrData.length; i++){
                        if(i == arrData.length - 1){
                            data = data + arrData[i];
                        }else{
                            data = data + arrData[i] + ",";
                        }
                    }
                    data = data + ")\n";
            
                try {
                    fos = new FileOutputStream(file, true);
                    fos.write(data.getBytes());
                    fos.close();
                } catch (IOException ex) {
                    Logger.getLogger(utilField.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
    
    private void updateComponent(Component selectedComponent){
    
        selectedComponent.getName();
        String[] fieldData = new String[6];
        
        //para sa name
        if(selectedComponent instanceof javax.swing.JLabel)
            fieldData[0] = ((javax.swing.JLabel)selectedComponent).getText();
        else
            fieldData[0] = "";
        
        //para sa accessibility
        if(selectedComponent.isVisible()){
            fieldData[1] = "1";
        }else{
            fieldData[1] = "0";
        }
        if(!selectedComponent.isEnabled()){
            fieldData[1] = "-1";
        }
        //para sa bounds
        fieldData[2] = String.valueOf(selectedComponent.getX());
        fieldData[3] = String.valueOf(selectedComponent.getY());
        fieldData[4] = String.valueOf(selectedComponent.getWidth());
        fieldData[5] = String.valueOf(selectedComponent.getHeight());
        
        fieldMap.remove(selectedComponent.getName());
        fieldMap.put(selectedComponent.getName(), fieldData);
        
        writeConfig(selectedComponent);

    }
    
    public class ComponentMover extends javax.swing.event.MouseInputAdapter{
    
        Component selectedComponent;
        Point offset;
        boolean dragging;
 
        public ComponentMover()
        {
            dragging = false;
        }
	
 
	public void mouseClicked(MouseEvent e){
		
            if(e.getButton() == MouseEvent.BUTTON3){
                selectedComponent = (Component)e.getSource();
                openPopup(selectedComponent);
            }
		
	}
 
        public void mousePressed(MouseEvent e)
        {
            if((e.getButton() == MouseEvent.BUTTON1)){
                selectedComponent = (Component)e.getSource();
                offset = e.getPoint();
                dragging = true;
            }
        }
 
        public void mouseReleased(MouseEvent e)
        {
            dragging = false;
            updateComponent((Component)e.getSource());
        }
 
        public void mouseDragged(MouseEvent e)
        {
            if(dragging)
            {
                Rectangle r = selectedComponent.getBounds();
                r.x += e.getX() - offset.x;
                r.y += e.getY() - offset.y;
                selectedComponent.setBounds(r);
            }
        }
        
    
    }
    
}
